<?php

namespace fast;

//易深支付
class Shanfu
{
    private string $apiUrl = 'http://customer.gzblkj.cn';
    private string $channelCode = "tmkj1";

    private string $merchantNo = "31116";
    private string $APP_ID = "128831116";
    private string $md5Key = "CvpZllDhaooi3Le2j15MySd2YiFkltCt";

    public function __construct()
    {

    }


    /**
     * 绑卡申请 发送短信
     *
     * @param string $merId       进件返回的商户ID
     * @param string $channelType 通道类型，请联系业务配置 例如 klt01
     * @param string $name        姓名
     * @param string $idNo        身份证号
     * @param string $mobile      手机号，银行留存的手机号
     * @param string $cardNo      银行卡号
     * @param string $cvn2        CVN2 信用卡必传
     * @param string $expired     有效期：YYMM，信用卡必传
     *
     * @return mixed
     */
    /**
     * 5.1快捷支付接口
     * @return mixed
     */
    public function quickpay(string $orderNo, string $cardNum, string $accountName, string $accountNumb, string
                                    $mobile, string
                                    $settleBankNumb, string $settleBankMobile, string $amount, string $fee, string
                                    $withdrawFee,string $clientIp, string $cvn2, string $expired, string $cityName,string $provName,string $bizChid,string $bankNumber): mixed
    {
        $notifyUrl = Config::get('site.notify_domain') . '/callback/channel/shanfu?method=quickpay&amp;brand_id='.$this->brandId;
        $method = "/api/kj/paySms";
        $params = [
            'channelCode'    => $this->channelCode,
            'outTradeNo'        => $orderNo,
            'subject'        => '收款',
            'memberName'        => $accountName,
            'certNo'        => $cardNum,
            'cardType'        => "C",
            'cardNo'        => $accountNumb,
            'phoneNo'        => $mobile,
            'cvn2'        => $cvn2,
            'validDate'        => $expired,
            'txnAmount'        => intval($amount * 100),
            'charge'        => intval($withdrawFee * 100),
            'notifyUrl'        => $notifyUrl,
        ];
        $resp  = $this->execute($method,$params);

        return $resp;

    }


    /**
     * 5.2快捷支付确认接口
     * @return mixed
     */
    public function quickpayConfirm(string $merId, string $orderNo, string $prepayId, string $smsCode, string $cvn2, string $expired,string $bankInputPhone): mixed
    {
        $method = '/api/kj/payConfirm';
        $params = [
            'smsNo'       => $prepayId,
            'smsCode'       => $smsCode,
        ];
        $resp  = $this->execute($method,$params,$orderNo);
        return $resp;
    }


    /**
     * 5.3单笔付款接口
     * @return mixed
     */
    public function singlePayment(string $orderNo, string $amount, string $withdrawFee,string $bankNumber, string $accountNumb, string $accountName, string
                                         $mobile, string $cardNum): mixed{


        $notifyUrl = Config::get('site.notify_domain') . '/callback/channel/shanfu?method=singlePayment&amp;brand_id=' .$this->brandId;
        $method = "/api/kj/agencyPay";
        $params = [
            'channelCode'       => $this->channelCode,
            'outTradeNo'        => $orderNo,
            'subject'           => '购买Huawei Mate60',
            'notifyUrl'          => $notifyUrl,
            'txnAmount'         => intval($amount * 100),
            'charge'            => intval($withdrawFee *100),
            'memberName'            => $accountName,
            'certNo'            => strtoupper($cardNum),
            'cardType'            => "D",
            'cardNo'            => $accountNumb,
            'phoneNo'            => $mobile,
        ];
        $resp  = $this->execute($method,$params);
        return $resp;
    }


    /**
     * 5.9订单查询接口
     * @param string $orderNo 商户订单号
     * @param string $startDate 开始日期，date("Ymd")
     * @param string $endDate 结束日期，date("Ymd")
     * @param string $tradeType //交易类型（收款：1；付款：2）
     * @return mixed
     */
    public function querySingleOrder(string $orderNo,string $tradeType,$tradeNo = ''): mixed
    {

        if($tradeType == 1){
            $method = "/api/kj/queryAgencyPay";
        }else{
            $method = "/api/kj/queryOrder";
        }


        $params = [
            'tradeNo'      => $tradeNo,
            'outTradeNo'      => $orderNo,
        ];
        $resp  = $this->execute($method,$params);
        return $resp;
    }

    /**
     * 请求
     */
    public function execute($method,$params,$orderNo='')
    {
        $params = $this->execute1($params,$orderNo);

        // 记录请求参数
        $requestId = uniqid(true);
        $url = $this->apiUrl.$method;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 1800);

        $header = ["content-type: application/json; charset=UTF-8"];
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));

        $response = curl_exec($ch);
        curl_close($ch);
        $res = $this->checkResult($response,$method);
        return $res;
    }

    public function execute1($params,$orderNo='')
    {
        $public = [
            'mechId' => $this->merchantNo,
            'appId' => $this->APP_ID,
            'timestamp' => date("Y-m-d H:i:s"),
            'nonceStr' => md5(uniqid()),
            'version' => '1.0',
            'signMethod' => 'md5',
        ];
        $params = array_merge($params,$public);
        $params["sign"] = $this->createSign($params,$this->md5Key);
        return $params;
    }


    function createSign($params, $md5Key) {
        // 过滤空参数
        $params = array_filter($params, function($value) {
            return !is_null($value) && $value !== '';
        });
        ksort($params); // 按参数名升序排序
        //$this->AsciiSort($params)
        $stringToSign = '';
        foreach ($params as $key => $value) {
            if ($key != 'sign' && $value != '') {
                $stringToSign .= $key . '=' . $value . '&';
            }
        }
        $stringToSign = trim($stringToSign,'&').$md5Key;
        return md5($stringToSign);
    }


    public function isSuccess($result): bool
    {
        if (empty($result)) {
            return false;
        }
        if (is_array($result) && $result['code'] == '1') {
            return true;
        } else {
            return false;
        }
    }

    /**
     *检查返回的结果
     */
    private function checkResult($result,$method)
    {

        $arr = json_decode($result, true);
        $arr['code'] = match ($arr['respCode']) {
            'TC0000',     => '1',
            default => '0'
        };
        $arr['message'] = $arr['respMsg'];
        $arr['err_msg'] = $arr['respMsg'];
        $arr['mer_id'] = $this->merchantNo;
        $arr['mer_code'] = $this->channelCode;

        ///api/kj/paySms
        if (isset($arr['txnStatus'])){
            $arr['status'] = match ($arr['txnStatus']) {
                'N'     => CommonConstant::QUICKPAY_STATUS_CREATE,
                'S'     => CommonConstant::QUICKPAY_STATUS_SUCCESS,
                'CF','F','C'     => CommonConstant::QUICKPAY_STATUS_FAIL,
                'UP','IP','SP'    => CommonConstant::QUICKPAY_STATUS_PAYING,
                default => CommonConstant::QUICKPAY_STATUS_PAYING
            };
        }

        $arr['prepay_id'] = isset($arr['smsNo']) ? $arr['smsNo'] : '';
        $arr['trans_no'] = isset($arr['outTradeNo']) ? $arr['outTradeNo'] : '';
        $arr['order_no'] = isset($arr['outTradeNo']) ? $arr['outTradeNo'] : '';

        $arr['data'] = $arr;
        return $arr;
    }

    /**
     * [foo 对返回数据按照第一个字符的键值ASCII码递增排序]
     */
    private function AsciiSort(&$ar): void
    {
        if (is_array($ar)) {
            ksort($ar);
            foreach ($ar as &$v)
                $this->AsciiSort($v);
        }
    }
}